/***
 * Julia: France Telecom's implementation of the Fractal API
 * Copyright (C) 2001-2002 France Telecom R&D
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 * Contact: Eric.Bruneton@rd.francetelecom.com
 *
 * Author: Eric Bruneton
 */

package fr.jade.fraclite.control.lifecycle;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.PrintStream;
import java.io.PrintWriter;

import org.objectweb.fractal.api.Component;
import org.objectweb.fractal.api.Interface;
import org.objectweb.fractal.api.NoSuchInterfaceException;
import org.objectweb.fractal.api.control.IllegalLifeCycleException;

import fr.jade.fraclite.util.Util;

/**
 * A sub class of the {@link IllegalLifeCycleException} class.
 */

public class ChainedIllegalLifeCycleException
  extends IllegalLifeCycleException
{

  /**
   * The exception that caused this exception. May be <tt>null</tt>.
   */

  private final Throwable exception;

  /**
   * The component whose life cycle state is illegal.
   */

  private transient Component component;

  /**
   * Constructs a new {@link ChainedIllegalLifeCycleException} exception.
   *
   * @param exception the cause of this exception. May be <tt>null</tt>.
   * @param component the component whose life cycle state is illegal.
   * @param message a detailed error message.
   */

  public ChainedIllegalLifeCycleException (
    final Throwable exception,
    final Component component,
    final String message)
  {
    super(message);
    this.exception = exception;
    this.component = component;
  }

  /**
   * Returns the exception that caused in this exception.
   *
   * @return the exception that caused this exception. May be <tt>null</tt>.
   */

  public Throwable getException () {
    return exception;
  }

  /**
   * Returns the component whose life cycle state is illegal.
   *
   * @return the component whose life cycle state is illegal.
   */

  public Component getComponent () {
    if (component != null && !(component instanceof Interface)) {
      try {
        return (Component)component.getFcInterface("component");
      } catch (NoSuchInterfaceException ignored) {
      }
    }
    return component;
  }

  // -------------------------------------------------------------------------
  // Overriden Exception methods
  // -------------------------------------------------------------------------

  /**
   * Returns a String representation of this exception.
   *
   * @return a String representation of this exception.
   */

  public String toString () {
    StringBuffer buf = new StringBuffer();
    buf.append("IllegalLifeCycleException: ");
    buf.append(getMessage());
    if (getComponent() != null) {
      buf.append(" (component = ");
      Util.toString(getComponent(), buf);
      buf.append(')');
    }
    return buf.toString();
  }

  /**
   * Prints the stack backtrace.
   */

  public void printStackTrace () {
    if (exception != null) {
      System.err.println(this);
      exception.printStackTrace();
    } else {
      super.printStackTrace();
    }
  }

  /**
   * Prints this exception and its backtrace to the specified print stream.
   *
   * @param s <tt>PrintStream</tt> to use for output.
   */

  public void printStackTrace (final PrintStream s) {
    if (exception != null) {
      s.println(this);
      exception.printStackTrace(s);
    } else {
      super.printStackTrace(s);
    }
  }

  /**
   * Prints this exception and its backtrace to the specified print writer.
   *
   * @param s <tt>PrintWriter</tt> to use for output.
   */

  public void printStackTrace (final PrintWriter s) {
    if (exception != null) {
      s.write(this + "\n");
      exception.printStackTrace(s);
    } else {
      super.printStackTrace(s);
    }
  }
  
  private void writeObject (final ObjectOutputStream out) throws IOException {
    out.defaultWriteObject();
    Component c = getComponent();
    out.writeObject(c instanceof Interface ? c : null);
  }

  private void readObject (final ObjectInputStream in)
    throws IOException, ClassNotFoundException
  {
    in.defaultReadObject();
    component = (Component)in.readObject();
  }
}
